 /*
 *	ME2 C++ SDK
 *	Copyright (c) 2010 _silencer
 *
 *	Permission is hereby granted, free of charge, to any person
 *	obtaining a copy of this software and associated documentation
 *	files (the "Software"), to deal in the Software without
 *	restriction, including without limitation the rights to use,
 *	copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the
 *	Software is furnished to do so, subject to the following
 *	conditions:
 *
 *	The above copyright notice and this permission notice shall be
 *	included in all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *	OTHER DEALINGS IN THE SOFTWARE.
 */

#include "stdafx.h"
#include "unreal_property.h"
#include "unreal_class.h"

namespace unreal
{
	std::string& uproperty::type_to_native( std::string& type_str )
	{
		if ( type_str == "Byte" )
			type_str = "int8";
		else
		if ( type_str == "Int" )
			type_str = "int32";
		else
		if ( type_str == "String" )
			type_str = "ustring";
		else
		if ( type_str == "Bool" )
			type_str = "bool";
		else
		if ( type_str == "Object" )
			type_str = "uobject";
		else
		if ( type_str == "TextBuffer" )
			type_str = "utext_buffer";
		else
		if ( type_str == "Component" )
			type_str = "ucomponent";
		else
		if ( type_str == "Field" )
			type_str = "ufield";
		else
		if ( type_str == "Enum" )
			type_str = "uenum";
		else
		if ( type_str == "Const" )
			type_str = "uconst";
		else
		if ( type_str == "Property" )
			type_str = "uproperty";
		else
		if ( type_str == "ByteProperty" )
			type_str = "ubyteproperty";
		else
		if ( type_str == "IntProperty" )
			type_str = "uintproperty";
		else
		if ( type_str == "BoolProperty" )
			type_str = "uboolproperty";
		else
		if ( type_str == "FloatProperty" )
			type_str = "ufloatproperty";
		else
		if ( type_str == "ObjectProperty" )
			type_str = "uobjectproperty";
		else
		if ( type_str == "ClassProperty" )
			type_str = "uclassproperty";
		else
		if ( type_str == "NameProperty" )
			type_str = "unameproperty";
		else
		if ( type_str == "ArrayProperty" )
			type_str = "uarrayproperty";
		else
		if ( type_str == "MapProperty" )
			type_str = "umapproperty";
		else
		if ( type_str == "StrProperty" )
			type_str = "ustrproperty";
		else
		if ( type_str == "StructProperty" )
			type_str = "ustructproperty";
		else
		if ( type_str == "ComponentProperty" )
			type_str = "ucomponentproperty";
		else
		if ( type_str == "Struct" )
			type_str = "ustruct";
		else
		if ( type_str == "Function" )
			type_str = "ufunction";
		else
		if ( type_str == "State" )
			type_str = "ustate";
		else
		if ( type_str == "Class" )
			type_str = "uclass";

		return type_str;
	}

	const uproperty::type_info uproperty::get_type() const
	{
		if ( is_a( ubyteproperty::static_get_class() ) )
		{
			return type_info( "Byte" );
		}

		if ( is_a( uintproperty::static_get_class() ) )
		{
			return type_info( "Int" );
		}

		if ( is_a( uboolproperty::static_get_class() ) )
		{
			return type_info( "Bool" );
		}

		if ( is_a( ufloatproperty::static_get_class() ) )
		{
			return type_info( "Float" );
		}

		if ( is_a( uobjectproperty::static_get_class() ) )
		{
			const uobjectproperty* object( reinterpret_cast<const uobjectproperty*>(this) );
			uclass* object_class( object->get_object_class() );

			if ( object_class->is_valid() )
				return type_info( object_class->get_name(), true );
			else
				return type_info( "/*Warning unknown type, defaulting to*/ Object", true );
		}

		if ( is_a( uclassproperty::static_get_class() ) )
		{
			const uclassproperty* object( reinterpret_cast<const uclassproperty*>(this) );
			uclass* object_class( object->get_object_class() );

			if ( object_class->is_valid() )
				return type_info( object_class->get_name(), true );
			else
				return type_info( "/*Warning unknown type, defaulting to*/ Class", true );
		}

		if ( is_a( unameproperty::static_get_class() ) )
		{
			return type_info( "Name" );
		}

		if ( is_a( uarrayproperty::static_get_class() ) )
		{
			const uarrayproperty* object( reinterpret_cast<const uarrayproperty*>(this) );
			uproperty* inner_property( object->get_inner_property() );
			
			type_info type( "Array" );

			if ( inner_property->is_valid() )
				type.inner.push_back( inner_property->get_type() );
			else
				type.inner.push_back( type_info( "/*Warning unknown type, defaulting to*/ Int" ) );

			return type;
		}

		if ( is_a( umapproperty::static_get_class() ) )
		{
			const umapproperty* object( reinterpret_cast<const umapproperty*>(this) );
			uproperty* key_property( object->get_key_property() );
			uproperty* value_property( object->get_value_property() );

			type_info type( "Map" );
			
			if ( key_property->is_valid() )
				type.inner.push_back( key_property->get_type() );
			else
				type.inner.push_back( type_info( "/*Warning unknown type, defaulting to*/ Int" ) );

			if ( value_property->is_valid() )
				type.inner.push_back( value_property->get_type() );
			else
				type.inner.push_back( type_info( "/*Warning unknown type, defaulting to*/ Int" ) );

			return type;
		}

		if ( is_a( ustrproperty::static_get_class() ) )
		{
			return type_info( "String" );
		}

		if ( is_a( ustructproperty::static_get_class() ) )
		{
			const ustructproperty* object( reinterpret_cast<const ustructproperty*>(this) );
			ustruct* structure( object->get_struct() );

			if ( structure->is_valid() )
				return type_info( structure->get_name() );
			else
				return type_info( "/*Warning unknown type, defaulting to*/ Struct" );
		}

		if ( is_a( ucomponentproperty::static_get_class() ) )
		{
			const ucomponentproperty* object( reinterpret_cast<const ucomponentproperty*>(this) );
			uclass* object_class( object->get_object_class() );

			if ( object_class->is_valid() )
				return type_info( object_class->get_name(), true );
			else
				return type_info( "/*Warning unknown type, defaulting to*/ Component", true );
		}

		return type_info( get_name() );
	}
}
